﻿using Microsoft.AspNetCore.Mvc.RazorPages;
using MongoDb.Api.Common;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System.Linq.Expressions;

namespace MongoDb.Api.Repository
{
    /// <summary>
    /// MongoDB操作类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseRepository<T> : IBaseRepository<T> where T : class
    {
        private readonly IMongoCollection<T> _client;
        public BaseRepository()
        {
            //建立mongodb连接
            var client = new MongoClient("mongodb://localhost:27017");
            //获取数据库实例
            var database = client.GetDatabase("TestMongodb");
            //获取当前表操作实例
            _client = database.GetCollection<T>("");
        }

        public void Create(T T)
        {
            _client.InsertOne(T);
        }
        public void CreateList(List<T> Ts)
        {
            _client.InsertMany(Ts);
        }

        public IEnumerable<T> GetTs()
        {
            return _client.AsQueryable<T>().ToList();
        }
        public T GetTById(string id)
        {
            return _client.Find(id).FirstOrDefault();
        }
        public IEnumerable<T> GetTsByPage(int Page, int PageSize)
        {
            var skipTotal = (Page - 1) * PageSize;
            return _client.AsQueryable<T>().Skip(skipTotal).ToList();
        }
        public IEnumerable<T> GetTsBySort(T T, int page, int pageSize, string sortField)
        {
            var filterDefinition = Builders<T>.Filter.Empty;
            //排序规则，假设你有一个字段名为"SortField"用于排序
            sortField = string.IsNullOrEmpty(sortField) ? "Id" : sortField;
            var sortDefinition = Builders<T>.Sort.Descending(sortField);
            var skipCount = (page - 1) * pageSize;
            var result = _client.Find(filterDefinition)
                                      .Sort(sortDefinition)
                                      .Skip(skipCount)
                                      .Limit(pageSize)
                                      .ToList();
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task<int> GetTotalCountWithAggregationAsync()
        {
            // 聚合阶段：对整个集合进行计数
            var groupStage = new BsonDocument("$group", new BsonDocument
            {
                { "_id", BsonNull.Value },
                { "totalCount", new BsonDocument("$sum", 1) }
            });

            var pipeline = new[] { groupStage };

            using IAsyncCursor<BsonDocument> cursor = await _client.AggregateAsync<BsonDocument>(pipeline);

            await cursor.MoveNextAsync();

            if (cursor.Current.Any())
            {
                return cursor.Current.First()["totalCount"].ToInt32();
            }

            return 0;
        }

        /// <summary>
        /// 单项更新
        /// </summary>
        /// <param name="id">要更新的文档的ID字段（假设为字符串类型）</param>
        /// <param name="entity">包含更新内容的新实体对象</param>
        public void Update(string id, T entity)
        {
            var filter = Builders<T>.Filter.Eq("_id", id); // 假设_id是你文档的主键字段

            var update = Builders<T>.Update.Set(x => x, entity); // 将整个实体更新到文档中

            _client.UpdateOne(filter, update);
        }

        /// <summary>
        /// 批量更新（基于ID和更新内容的字典）
        /// </summary>
        /// <param name="updates">一个字典，键是ID，值是要更新的对象</param>
        public void UpdateList(Dictionary<string, T> updates)
        {
            foreach (var update in updates)
            {
                var filter = Builders<T>.Filter.Eq("_id", update.Key);
                var updateDefinition = Builders<T>.Update.Set(x => x, update.Value);
                _client.UpdateOne(filter, updateDefinition);
            }
        }

        /// <summary>
        /// 单项删除
        /// </summary>
        /// <param name="entity">包含待删除文档ID的实体对象</param>
        public void Delete(string id)
        {
            var filter = Builders<T>.Filter.Eq("_id", id); // 假设Id是T类型的实体主键属性

            _client.DeleteOne(filter);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="filterIds">包含待删除文档ID的实体对象列表</param>
        public void DeleteList(List<string> filterIds)
        {
            List<FilterDefinition<T>> filters = new List<FilterDefinition<T>>();

            foreach (var Id in filterIds)
            {
                var filter = Builders<T>.Filter.Eq("_id", Id); // 假设Id是T类型的实体主键属性
                filters.Add(filter);
            }

            // 如果你想一次性删除所有符合这些过滤条件的文档：
            var combinedFilter = Builders<T>.Filter.Or(filters);
            _client.DeleteMany(combinedFilter);
        }

        /// <summary>
        /// 数据是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool TExists(string id)
        {
            var filter = Builders<T>.Filter.Eq("_id", id); // 假设_id字段是string类型
            return _client.Find(filter).Any();
        }

        /// <summary>
        /// 修改（替换整个文档）
        /// </summary>
        /// <param name="id">要被替换文档的ID（通常为ObjectId或自定义主键）</param>
        /// <param name="newEntity">替换的新实体对象</param>
        public void Replace(string id, T newEntity)
        {
            var filter = Builders<T>.Filter.Eq("_id", id); // 假设_id字段是string类型

            var replaceOptions = new ReplaceOptions { IsUpsert = true }; // 可选：如果文档不存在，则插入新文档

            _client.ReplaceOne(filter, newEntity, replaceOptions);
        }

        /// <summary>
        /// 创建索引
        /// </summary>
        /// <param name="indexKeys">索引键的定义，例如：Builders<T>.IndexKeys.Ascending("FieldName")</param>
        /// <param name="indexOptions">(可选)索引选项，例如：new CreateIndexOptions() { Unique = true }</param>
        /// <returns>创建索引的命令结果，包含了索引名称等信息</returns>
        public CreateIndexModel<T> CreateIndex(IndexKeysDefinition<T> indexKeys, CreateIndexOptions indexOptions = null)
        {
            var indexModel = new CreateIndexModel<T>(indexKeys, indexOptions);

            // 创建索引
            var result = _client.Indexes.CreateOne(indexModel);

            // 返回创建的索引模型信息
            return indexModel;
        }



    }

}
